/*
 * SMRoundTrim.java
 *
 * Created on 29 Март 2008 г., 17:21
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package trim.calc;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import trim.Trim;
import trim.TrimException;
import trim.common.inputdata.FormatOrder;
import trim.common.inputdata.InputData;
import trim.common.result.TrimResult;
import trim.common.sm.SMException;
import trim.common.sm.SimpleTrimSMData;
import trim.common.sm.TrimSimplex;
import trim.common.utils.Utils;

/**
 *
 * @author Дмитрий
 */
public class SMRoundTrim extends Trim
{

  /** Creates a new instance of SMRoundTrim */
  public SMRoundTrim()
  {
  }

  @Override
  public TrimResult solve(InputData inputData) throws TrimException
  {
    try
    {
      inputData=Utils.groupInputData(inputData).clone();
      TrimSimplex sm=new TrimSimplex(new SimpleTrimSMData(inputData));
      sm.solve();
      new Round().round(sm);
      TrimResult tr=sm.getTrimResult();
      return tr;
    }catch(SMException ex)
    {
      throw new TrimException("Error in SM",ex);
    }
  }

  /**
   * Класс передназначенный для округления решения СМ
   */
  private class Round
  {

    int[] additions;
    double[] res1;
    int minm;
    double[] objFunc;
    TrimSimplex sm;
    int n;

    Round()
    {
    }

    void round(TrimSimplex sm)
    {
      this.sm=sm;
      objFunc=sm.getObjectiveFunction();
      n=objFunc.length;
      additions=new int[n];
      int c=0;
      for(int i=0;i<n;i++)
      {
        additions[i]=(objFunc[i]-Math.floor(objFunc[i]+1e-10))>1e-10?1:0;
        objFunc[i]=Math.floor(objFunc[i]+1e-10);
        c+=additions[i];
      }
      if(c<15)
      {
        res1=new double[n];
        minm=10000000;
        SrchL(0);
        for(int i=0;i<n;i++)
          objFunc[i]=res1[i];
        res1=null;
      }else
        for(int i=0;i<n;i++)
          objFunc[i]=Math.floor(objFunc[i]+1e-10)+additions[i];
    }

    private void SrchL(int cnt)
    {
      if(cnt==n)
      {
        List<FormatOrder> rest=sm.getRestFormatCount();
        int k=0;
        for(FormatOrder fc:rest)
          k+=Math.abs(fc.getCount());

        if(k<minm)
          for(int i=0;i<n+0;i++)
            res1[i]=objFunc[i];
      //delete [] L1;

      }else
      {
        for(int i=0;i<=additions[cnt];i++) //		if(L[cnt]-i>=0)
        {
          objFunc[cnt]+=i;
          SrchL(cnt+1);
          objFunc[cnt]-=i;
        }
      }
      return;
    }
  }

  @Override
  public String getName()
  {
    return this.getClass().getSimpleName();
  }

  @Override
  public String getVersion()
  {
    InputStream is=getClass().getResourceAsStream("/trim/calc/version");
    byte[] b=new byte[20];
    try
    {
      int n=is.read(b);
      return new String(b,0,n);
    }catch(IOException ex)
    {
      ex.printStackTrace();
      return "0";
    }
  }

  @Override
  public String getDescription()
  {
    return "Округление решения СМ";
  }
}
